package com.yanqu.road.server.gameplayer.module.activity.chess;

import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.chinesechess.*;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.config.goods.MallInfo;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.enums.activity.chinesechess.eChineseChessGameStatusType;
import com.yanqu.road.entity.enums.activity.chinesechess.eChineseChessLogTypeType;
import com.yanqu.road.entity.enums.activity.chinesechess.eChineseChessPiecesType;
import com.yanqu.road.entity.log.LogChineseChessMove;
import com.yanqu.road.logic.bussiness.activity.ChineseChessBusiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.pb.activity.ChineseChessProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.manger.activity.chinesechess.ChineseChessMgr;
import com.yanqu.road.server.manger.config.GoodsMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.CrossProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


public class ChineseChessModule extends GeneralModule {


    private ChineseChessUserData userData;

    public ChineseChessModule(GamePlayer player) {
        super(player);
    }

    public ChineseChessUserData getUserData(){
        return userData;
    }

    public void rechargeToken(int activityId, MallInfo mallInfo){
        if(userData.getActivityId() != activityId){
            return;
        }
        BigInteger value = userData.getTopScore();
        if(userData.getScore().compareTo(userData.getTopScore()) > 0){
            value = userData.getScore();
        }
        if(mallInfo.getShopType() == eShopType.ChineseChessSilverToken.getValue()){
            player.notifyListener(eGamePlayerEventType.ChineseChessSilverToken.getValue(), value);
            userData.setBuySilverToken(true);
        }
        if(mallInfo.getShopType() == eShopType.ChineseChessGoldToken.getValue()){
            player.notifyListener(eGamePlayerEventType.ChineseChessGoldToken.getValue(), value);
            userData.setBuyGoldToken(true);
        }
        crossSyncUserData();
    }

    //购买后设置可以复活
    public void canRevive(int goodsId, long longValue, eLogMoneyType master, eLogMoneyType son) {
        userData.setReviveSelf(true);
        player.getModule(ChineseChessPracticeModule.class).canRevive();
    }

    public boolean isBuyToken(MallInfo mallInfo) {
        if(mallInfo.getShopType() == eShopType.ChineseChessSilverToken.getValue()){
            return userData.isBuySilverToken();
        }
        if(mallInfo.getShopType() == eShopType.ChineseChessGoldToken.getValue()){
            return userData.isBuyGoldToken();
        }
        return false;
    }

    //强化后无视阻挡
    private int checkSelfMove(int x,int y,boolean isPowerOn){
        if(userData.getGameStatus() != 0){
            return GameErrorCode.E_CHINESECHESS_GAME_MOVE;
        }
        Map<Integer, ChineseChessData> chessMap = userData.getChessMap();
        ChineseChessData selfChess = chessMap.get(0);
        //判断是不是直线运动
        if(selfChess.getPosition().getX() != x && selfChess.getPosition().getY() != y){
            return GameErrorCode.E_CHINESECHESS_GAME_MOVE;
        }
        //是不是越界了
        if(x < 0 || y < 0 || x >= ChineseChessMgr.getX() || y >= ChineseChessMgr.getY()){
            return GameErrorCode.E_CHINESECHESS_GAME_MOVE;
        }
        //检验移动是不是出现前面有棋子挡住
        if(!isPowerOn){
            for(ChineseChessData chess :chessMap.values()){
                if(chess.getChessNo() == 0){
                    if(chess.getPosition().getX() == x && chess.getPosition().getY() == y){
                        return GameErrorCode.E_CHINESECHESS_GAME_MOVE;
                    }
                    continue;
                }
                if(selfChess.getPosition().getX() == x){//y轴运动
                    if(y > selfChess.getPosition().getY() && chess.getPosition().getX() == x
                            && chess.getPosition().getY() < y && chess.getPosition().getY() > selfChess.getPosition().getY()){
                        return GameErrorCode.E_CHINESECHESS_GAME_MOVE;
                    }
                    if(y < selfChess.getPosition().getY() && chess.getPosition().getX() == x
                            && chess.getPosition().getY() > y && chess.getPosition().getY() < selfChess.getPosition().getY()){
                        return GameErrorCode.E_CHINESECHESS_GAME_MOVE;
                    }
                }else if(selfChess.getPosition().getY() == y){//x轴运动
                    if(x > selfChess.getPosition().getX() && chess.getPosition().getY() == y
                            && chess.getPosition().getX() < x && chess.getPosition().getX() > selfChess.getPosition().getX()){
                        return GameErrorCode.E_CHINESECHESS_GAME_MOVE;
                    }
                    if(x < selfChess.getPosition().getX() && chess.getPosition().getY() == y
                            && chess.getPosition().getX() > x && chess.getPosition().getX() < selfChess.getPosition().getX()){
                        return GameErrorCode.E_CHINESECHESS_GAME_MOVE;
                    }
                }else{
                    return GameErrorCode.E_CHINESECHESS_GAME_MOVE;
                }
            }
        }
        return 0;
    }

    private void logErrChess(int x,int y){
        Map<Integer, ChineseChessData> chessMap = userData.getChessMap();
//        log.error(getUserId() + "当前局数{};当前步数{}",userData.getGameNo(),userData.getStep() + 1);
//        log.error(getUserId() + "玩家棋子:{}",chessMap.get(0).getPosition().getX() + ";" + chessMap.get(0).getPosition().getY());
        String chessStr = "";
        for(ChineseChessData chess : chessMap.values()){
            if(chess.getChessNo() == 0)continue;
            chessStr += chess.getPosition().getX() + ";" + chess.getPosition().getY() + ";" + chess.getChessId() + "|";
        }
        if(chessStr.length() > 0){
            chessStr = chessStr.substring(0,chessStr.length() -1);
        }
//        log.error(getUserId() + "敌人棋子:{}",chessStr);
//        log.error(getUserId() + "玩家移动位置:{}-{}",x,y);
    }

    /**
     * 先吃棋子，再AI行动，判断是不是被吃了，告诉客户端哪个吃的，新手保护直接回滚，加分数，判断下一轮生成
     * @param x int
     * @param y int
     * @param isPowerOn 是不是开启强化效果(强化效果可以无视障碍前进，清除沿途的所有地方棋子)
     * @return a
     */
    //策划改成发射导弹逻辑
    public int gameMoveVersion2(int x,int y,boolean isPowerOn){
        boolean isDieWithNoPower = isGoNoPowerDie();
        boolean isNoEatMove = false;
        if(userData.getStep() < ChineseChessMgr.getNewPlayerStep() && isDieWithNoPower){
            isNoEatMove = true;
        }
        String logChessDataStr = makeLogChessMapString(userData.getChessMap());
        int logType = eChineseChessLogTypeType.Move.getValue();
        int logPower = 0;
        List<ChineseChessData> logEatChessList = new ArrayList<>();
        boolean gameOver = false;
        //配置的通关步数达到了直接通关了
        if(userData.getStep() + 1 >= ChineseChessMgr.getGameOverStep()){
            gameOver = true;
        }
        logErrChess(x,y);
        int moveRet = checkSelfMove(x,y,isPowerOn);
        if(moveRet != 0){
            return moveRet;
        }
        int powerItemId = ChineseChessMgr.getPowerItemId();
        Property cost = PropertyHelper.parseStringToProperty(powerItemId + "=" + 1);
        if(isPowerOn){
            if(!player.getModule(CurrencyModule.class).currencyIsEnough(cost)){
                return GameErrorCode.E_CHINESECHESS_GAME_NO_POWER_ITEM;
            }
        }
        //原先的棋谱
        Map<Integer, ChineseChessData> oChessMap = new ConcurrentHashMap<>(userData.getChessMap());
        Map<Integer, ChineseChessData> chessMap = userData.getChessMap();
        ChineseChessData playerChess = chessMap.get(0);
        //原先的位置，新手保护要回滚回去
        ChineseChessPosition oPos = new ChineseChessPosition(playerChess.getPosition().getX(),playerChess.getPosition().getY());
        long eatChessAddScore = 0;
        List<ChineseChessData> eatChessList = new ArrayList<>();
        //有道具强化或者吃帅强化
        if(isPowerOn && userData.getPowerTimes() > 0){
            logPower = 3;
        }else if(userData.getPowerTimes() > 0){
            logPower = 2;
        }else if(isPowerOn){
            logPower = 1;
        }

        if(isPowerOn || userData.getPowerTimes() > 0){
            Map<String,ChineseChessPosition> posMap = new ConcurrentHashMap<>();
            if(isPowerOn){
                posMap.putAll(ChineseChessMgr.getPowerOnMovePosMap(playerChess,x,y));
            }
            if(userData.getPowerTimes() > 0){
                userData.setPowerTimes(userData.getPowerTimes() - 1);
                posMap.putAll(ChineseChessMgr.getKingPowerOnEatPosMap(x,y));
            }
            for(ChineseChessData chess : chessMap.values()){
                if(chess.getChessNo() == 0)continue;
                if(posMap.containsKey(chess.getPosition().getX() + "-" + chess.getPosition().getY())){
                    logEatChessList.add(chess);
                    if(chess.getChessId() == eChineseChessPiecesType.King.getValue()){
                        userData.setPowerTimes(ChineseChessMgr.getEatKingPowerTime());
                    }
                    eatChessList.add(chess);
                    eatChessAddScore += getSkinAddScore(ChineseChessMgr.getChessConfig(chess.getChessId()));
                }
            }
        }else{
            for(ChineseChessData chess : chessMap.values()){
                if(chess.getChessNo() == 0)continue;
                if(chess.getPosition().getX() == x && chess.getPosition().getY() == y){//吃了其他棋子
                    logEatChessList.add(chess);
                    if(chess.getChessId() == eChineseChessPiecesType.King.getValue()){
                        userData.setPowerTimes(ChineseChessMgr.getEatKingPowerTime());
                    }
                    eatChessList.add(chess);
                    eatChessAddScore = getSkinAddScore(ChineseChessMgr.getChessConfig(chess.getChessId()));
                }
            }
        }
        if(eatChessList.size() > 0){
            for(ChineseChessData eatChess : eatChessList){
                chessMap.remove(eatChess.getChessNo());
            }
        }
        playerChess.getPosition().setX(x);
        playerChess.getPosition().setY(y);
        //AI走棋
        ChineseChessData moveChess = ChineseChessMgr.getNextMove(chessMap,isNoEatMove);
        ChineseChessProto.ChineseChessMoveRespMsg.Builder msg = ChineseChessProto.ChineseChessMoveRespMsg.newBuilder();
        msg.setRet(0);
        //被吃了游戏结束
        if(moveChess != null && moveChess.getPosition().getX() == playerChess.getPosition().getX() && moveChess.getPosition().getY() == playerChess.getPosition().getY()){
            //新手保护直接不让走这一步，客户端自己表现被吃了又回滚
            if(userData.getStep() < ChineseChessMgr.getNewPlayerStep() && !gameOver){
                //编号0的是玩家自己
                oChessMap.get(0).setPosition(oPos);
                msg.setMoveChess(parseChineseChessDataPb(moveChess));
                moveChess.setPosition(moveChess.getLastPosition());
                userData.setChessMap(oChessMap);
                msg.setRet(GameErrorCode.E_CHINESECHESS_GAME_NOVICE);
                for(ChineseChessData chess : oChessMap.values()){
                    if(chess.getChessNo() == 0)continue;
                    msg.addChess(parseChineseChessDataPb(chess));
                }
                msg.setSelfChess(parseChineseChessDataPb(oChessMap.get(0)));
                msg.setScore(userData.getScore().longValue());
                player.sendPacket(Protocol.U_CHINESECHESS_GAME_MOVE, msg);
                addLog(eChineseChessLogTypeType.PlayerProtect.getValue(),logPower,eatChessAddScore,logEatChessList,logChessDataStr,"");
                return 0;
            }
            //有替身复活效果，直接原地复活
            if(userData.isReviveSelf() && userData.getReviveSelfTimes() == 0 && !gameOver){
                logEatChessList.add(moveChess);
                logType = eChineseChessLogTypeType.FenShenRevive.getValue();
                userData.setReviveSelfTimes(1);
                //原地复活直接吃了
                chessMap.remove(moveChess.getChessNo());
                if(moveChess.getChessId() == eChineseChessPiecesType.King.getValue()){
                    userData.setPowerTimes(ChineseChessMgr.getEatKingPowerTime());
                }
                ChineseChessConfig chessConfig = ChineseChessMgr.getChessConfig(moveChess.getChessId());
                eatChessAddScore += getSkinAddScore(chessConfig);
                msg.setIsRevive(1);
            }else{
                userData.setGameStatus(eChineseChessGameStatusType.Revive.getValue());
            }
        }
        if(isPowerOn){
            player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.ChineseChessActivity,eLogMoneyType.ChineseChessActivityGamePowerItem);
        }

        if(eatChessAddScore != 0){
            userData.setScore(userData.getScore().add(BigInteger.valueOf(eatChessAddScore)));
            if(userData.getScore().compareTo(userData.getTopScore()) > 0){
                noticeCondition(userData.getScore(),userData.getPassTime() > 0);
            }
        }

        Map<Integer, ChineseChessData> nextChessMap = userData.getNextChessMap();
        userData.setStep(userData.getStep() + 1);
        //生成下一轮棋子
        if(userData.getNextChessTurn() - 1 == 0){
            //生成帅和普通的不一样
            if(isKingNext(nextChessMap)){
                Map<Integer,ChineseChessData> makeMap = ChineseChessMgr.makeNextChessPosKing(userData.getStep(),nextChessMap,chessMap);
                if(makeMap != null){
                    chessMap.putAll(makeMap);
                }
            }else{
                Map<Integer,ChineseChessData> makeMap = ChineseChessMgr.makeNextChessPos(userData.getStep(),nextChessMap,chessMap);
                if(makeMap != null){
                    chessMap.putAll(makeMap);
                }
            }
            makeNextNewVersion();
        }else{
            if(userData.getNextChessTurn() > 0){
                userData.setNextChessTurn(userData.getNextChessTurn() - 1);
            }
        }
        userData.setChessMap(chessMap);


        for(ChineseChessData chess : chessMap.values()){
            if(chess.getChessNo() == 0)continue;
            msg.addChess(parseChineseChessDataPb(chess));
        }
        msg.setSelfChess(parseChineseChessDataPb(chessMap.get(0)));
        if(moveChess != null){
            msg.setMoveChess(parseChineseChessDataPb(moveChess));
        }
        msg.setNextTurn(userData.getNextChessTurn());
        for(ChineseChessData chess : userData.getNextChessMap().values()){
            if(chess.getChessNo() == 0)continue;
            msg.addNextChess(parseChineseChessDataPb(chess));
        }
        msg.setGameStatus(userData.getGameStatus());
        msg.setScore(userData.getScore().longValue());
        msg.setStep(userData.getStep());
        //如果场上没有棋子吃了也没有生成了也是直接通关
        if(userData.getNextChessMap().size() == 0 && userData.getChessMap().size() == 1){
            gameOver = true;
        }

        if(gameOver){
            userData.setPassTime(userData.getPassTime() + 1);
            userData.setGameStatus(eChineseChessGameStatusType.Pass.getValue());
            msg.setPassTimes(userData.getPassTime());
            //如果场上没有棋子吃了也没有生成了也是直接通关 和指定通关步数的差值转换成分数给用户
            int passStep = ChineseChessMgr.getGameOverStep() - userData.getStep();
            if(passStep >= 0){
                userData.setScore(userData.getScore().add(BigInteger.valueOf(passStep * ChineseChessMgr.getPassStepAdd())));
                if(userData.getScore().compareTo(userData.getTopScore()) > 0){
                    noticeCondition(userData.getScore(),true);
                }
            }
        }else{
            msg.setPassTimes(0);
        }
        player.sendPacket(Protocol.U_CHINESECHESS_GAME_MOVE, msg);
        addLog(logType,logPower,eatChessAddScore,logEatChessList,logChessDataStr,"");
        return 0;
    }

    private boolean debugMove = false;

    public void debugParam(){
        ChineseChessProto.ChineseChessGameDebugParamRespMsg.Builder respMsg = ChineseChessProto.ChineseChessGameDebugParamRespMsg.newBuilder();
        respMsg.setTongluValue(ChineseChessMgr.getPassRoadValue(userData.getChessMap()));
        respMsg.setOuheValue(ChineseChessMgr.getAllCouplingValue(userData.getChessMap()));
        player.sendPacket(Protocol.U_CHINESECHESS_GAME_DEBUG_PARAMS, respMsg);
    }

    public void debugWeight(int chessNo){
        ChineseChessProto.ChineseChessWeightDebugRespMsg.Builder respMsg = ChineseChessProto.ChineseChessWeightDebugRespMsg.newBuilder();
        respMsg.setRet(0);
        if(!userData.getNextChessMap().containsKey(chessNo)){
            respMsg.setRet(GameErrorCode.E_CHINESECHESS_GAME_ERR);
            player.sendPacket(Protocol.U_CHINESECHESS_GAME_WEIGHT_DEBUG, respMsg);
            return;
        }
        ChineseChessData nextChess = userData.getNextChessMap().get(chessNo);
        ChineseChessMoveConfig chessMoveConfig = ChineseChessMgr.getChessMoveDebugConfig(userData.getStep());
        Map<ChineseChessPosition,Integer> posWeightMap = ChineseChessMgr.getPosWeightMapVersion3(chessMoveConfig,nextChess,userData.getChessMap());
        if(posWeightMap == null){
            respMsg.setRet(GameErrorCode.E_CHINESECHESS_GAME_ERR);
            player.sendPacket(Protocol.U_CHINESECHESS_GAME_WEIGHT_DEBUG, respMsg);
            return;
        }
        BigDecimal allWeight = BigDecimal.ONE;
        for(int weight : posWeightMap.values()){
            allWeight = allWeight.add(BigDecimal.valueOf(weight));
        }
        for(ChineseChessPosition pos : posWeightMap.keySet()){
            ChineseChessProto.ChessWeightDebugTempMsg.Builder weightTmp = ChineseChessProto.ChessWeightDebugTempMsg.newBuilder();
            weightTmp.setX(pos.getX());
            weightTmp.setY(pos.getY());
            weightTmp.setWeight(BigDecimal.valueOf(posWeightMap.get(pos)).multiply(new BigDecimal(100)).divide(allWeight,2,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).intValue());
            respMsg.addWeight(weightTmp);
        }
        player.sendPacket(Protocol.U_CHINESECHESS_GAME_WEIGHT_DEBUG, respMsg);
    }

    public boolean isGoNoPowerDie(){
        if(userData.getGameStatus() != eChineseChessGameStatusType.Running.getValue()){
            return true;
        }
        Map<Integer, ChineseChessData> chessMap = userData.getChessMap();
        ChineseChessPosition pos = ChineseChessMgr.debugAutoMove(chessMap,false);
        if(pos != null){
            return false;
        }else{
            return true;
        }
    }

    public void debugAutoMove(){
        ChineseChessProto.ChineseChessGameDebugRespMsg.Builder msg = ChineseChessProto.ChineseChessGameDebugRespMsg.newBuilder();
        msg.setRet(0);
        synchronized (this){
            debugMove = true;
            if(userData.getGameStatus() != eChineseChessGameStatusType.Running.getValue()){
                debugMove = false;
                return;
            }
            Map<Integer, ChineseChessData> chessMap = userData.getChessMap();
            ChineseChessPosition pos = ChineseChessMgr.debugAutoMove(chessMap,false);
            if(pos != null){
                msg.setMoveX(pos.getX());
                msg.setMoveY(pos.getY());
                msg.setPower(false);
            }else{
                if(player.getModule(CurrencyModule.class).currencyIsEnough(PropertyHelper.parseStringToProperty(ChineseChessMgr.getPowerItemId() + "=" + 1))){
                    pos = ChineseChessMgr.debugAutoMove(chessMap,true);
                    if(pos != null){
                        msg.setMoveX(pos.getX());
                        msg.setMoveY(pos.getY());
                        msg.setPower(true);
                    }else{
                        msg.setRet(10086);
                    }
                }else{
                    msg.setRet(10086);
                }
            }
        }
        player.sendPacket(ClientProtocol.U_CHINESECHESS_GAME_DEBUG,msg);
    }

    //自动下棋
    public void debugAutoMove(int times){
        synchronized (this){
            if(debugMove && times == 0)return;
            if(times > 108){
                log.error(player.getUserId() + "的象棋大逃杀走了一百步");
                debugMove = false;
                return;
            }
            debugMove = true;
            if(userData.getGameStatus() != eChineseChessGameStatusType.Running.getValue()){
                debugMove = false;
                return;
            }
            Map<Integer, ChineseChessData> chessMap = userData.getChessMap();
            ChineseChessPosition pos = ChineseChessMgr.debugAutoMove(chessMap,false);
            if(pos != null){
                gameMoveVersion2(pos.getX(),pos.getY(),false);
                debugAutoMove(++times);
            }else{
                log.error(player.getUserId() + "的象棋大逃杀走不动了");
                if(player.getModule(CurrencyModule.class).currencyIsEnough(PropertyHelper.parseStringToProperty(ChineseChessMgr.getPowerItemId() + "=" + 1))){
                    log.error(player.getUserId() + "的象棋大逃杀走不动了开启强化");
                    pos = ChineseChessMgr.debugAutoMove(chessMap,true);
                    if(pos != null){
                        gameMoveVersion2(pos.getX(),pos.getY(),true);
                    }else{
                        log.error(player.getUserId() + "的象棋大逃杀走不动了开启强化也没用");
                    }
                }else{
                    log.error(player.getUserId() + "的象棋大逃杀走不动了没得开启强化");
                }
                debugMove = false;
            }
        }
    }

    //分数加成(千分比加起来加成)
    public long getSkinAddScore(ChineseChessConfig chessConfig){
        int add = 0;
        int score = chessConfig.getScore();
        BigInteger value = BigInteger.valueOf(score);
        List<Integer> hasSkinIdList = getHasSkinIdList();
        for(int skinId : chessConfig.getSkinIdList().keySet()){
            if(hasSkinIdList.contains(skinId)){
                add = add + chessConfig.getSkinIdList().get(skinId);
            }
        }
        ChineseChessConfig playerChessConfig = ChineseChessMgr.getChessConfig(0);
        for(int skinId : playerChessConfig.getSkinIdList().keySet()){
            if(hasSkinIdList.contains(skinId)){
                add = add + playerChessConfig.getSkinIdList().get(skinId);
            }
        }

        value = value.multiply(BigInteger.valueOf(1000).add(BigInteger.valueOf(add))).divide(BigInteger.valueOf(1000));
        return value.longValue();
    }

    public void noticeCondition(BigInteger value,boolean isPass){
        ChineseChessValueArgs args = new ChineseChessValueArgs(value,isPass?"1":"");
        player.notifyListener(eGamePlayerEventType.ChineseChessTopScoreRank.getValue(),args);
        player.notifyListener(eGamePlayerEventType.ChineseChessBronzeToken.getValue(), value);
        if(userData.isBuySilverToken()){
            player.notifyListener(eGamePlayerEventType.ChineseChessSilverToken.getValue(), value);
        }
        if(userData.isBuyGoldToken()){
            player.notifyListener(eGamePlayerEventType.ChineseChessGoldToken.getValue(), value);
        }
    }

    public void gameOver(int gameNo,int lastRank,int nowRank,int topRank){
        if(!ChineseChessMgr.activityInRewardPeriod() && eChineseChessGameStatusType.Revive.getValue() != userData.getGameStatus() && eChineseChessGameStatusType.Pass.getValue() != userData.getGameStatus()){
            return;
        }
        if(userData.getScore().longValue() > userData.getTopScore().longValue()){
            userData.setTopScore(userData.getScore());
        }
        boolean isFirstPass = false;
        if(userData.getPassTime() == 1 && userData.getGameStatus() == eChineseChessGameStatusType.Pass.getValue()){
            Property firstReward = ChineseChessMgr.getFirstPassReward();
            player.getModule(CurrencyModule.class).addCurrency(firstReward, eLogMoneyType.ChineseChessActivity,eLogMoneyType.ChineseChessActivityFirstPassReward);
            isFirstPass = true;
            addLog(eChineseChessLogTypeType.Pass.getValue(),0,0,null,null,PropertyHelper.parsePropertyToString(firstReward));
        }
        userData.setGameStatus(eChineseChessGameStatusType.Over.getValue());
        Property gameOverReward = ChineseChessMgr.getGameOverReward(userData.getScore().intValue());
        player.getModule(CurrencyModule.class).addCurrency(gameOverReward, eLogMoneyType.ChineseChessActivity,eLogMoneyType.ChineseChessActivityGameOverReward);

        ChineseChessProto.ChineseChessGameOperateRespMsg.Builder respMsg = ChineseChessProto.ChineseChessGameOperateRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setGameNo(gameNo);
        respMsg.setScore(userData.getScore().longValue());
        respMsg.setLastRank(lastRank);
        respMsg.setNowRank(nowRank);
        respMsg.setTopRank(topRank);
        respMsg.setIsFirstPass(isFirstPass);
        player.sendPacket(Protocol.U_CHINESECHESS_GAME_OPERATE, respMsg);
        addLog(eChineseChessLogTypeType.GameOver.getValue(),0,0,null,null,PropertyHelper.parsePropertyToString(gameOverReward));
    }

    private String makeLogChessSkinMapString(Map<Integer,ChineseChessSkinData> skinMap){
        String res = "";
        for(ChineseChessSkinData skinData : skinMap.values()){
            res = res + skinData.getChessId() + "=" + StringUtils.listToString(skinData.getSkinIdList(),",");
            res = res + "|";
        }
        return res.substring(0,res.length() - 1);
    }

    private String makeLogChessString(ChineseChessData chess){
        return chess.getPosition().getX() + "," + chess.getPosition().getY() + "-" + chess.getChessNo() + "_" + chess.getChessId();
    }

    private String makeLogChessMapString(Map<Integer,ChineseChessData> chessDataMap){
        String res = "";
        if(chessDataMap == null){
            return res;
        }
        List<ChineseChessData> chessList = new ArrayList<>(chessDataMap.values());
        for(int i = 0;i < chessList.size();i++){
            res = res + makeLogChessString(chessList.get(i));
            if(i != chessList.size() - 1){
                res = res + "|";
            }
        }
        return res;
    }

    private String makeLogChessListString(List<ChineseChessData> chessDataList){
        String res = "";
        if(chessDataList == null){
            return res;
        }
        for(int i = 0;i < chessDataList.size();i++){
            res = res + makeLogChessString(chessDataList.get(i));
            if(i != chessDataList.size() - 1){
                res = res + "|";
            }
        }
        return res;
    }

    public void addLog(int type,int power,long addscore,List<ChineseChessData> logEatChessList,String chessDataStr,String rewardStr){
        int activityId = userData.getActivityId();
        long userId = getUserId();
        int gameNo = userData.getGameNo();
        int step = userData.getStep();
        int opTypo = type;
        int endStep = ChineseChessMgr.getGameOverStep() - type;
        int isFenshen = userData.isReviveSelf()?1:0;
        long addScore = addscore;
        String eatChess = makeLogChessListString(logEatChessList);
        String nextChess = makeLogChessMapString(userData.getNextChessMap());
        String chessSkin = makeLogChessSkinMapString(userData.getChessSkinMap());
        String chessData = chessDataStr;
        String moveChessData = makeLogChessMapString(userData.getChessMap());
        long score = userData.getScore().longValue();
        String reward = rewardStr;
        LogChineseChessMove log = new LogChineseChessMove(activityId,userId,gameNo,step,opTypo,power,endStep,isFenshen,addScore,eatChess,nextChess,chessSkin,chessData,moveChessData,score,reward);
//        LogMgr.addLogChineseChessMove(log);
        AutoLogMgr.add(log);
    }

    public int gameOperate(int activityId,int gameNo,int type,int skinId){
        if(type != 3 && (activityId != userData.getActivityId() || (!ChineseChessMgr.activityInRewardPeriod() && userData.getGameNo() != gameNo))){
            return GameErrorCode.E_CHINESECHESS_GAME_ERR;
        }
        ChineseChessProto.ChineseChessGameOperateRespMsg.Builder respMsg = ChineseChessProto.ChineseChessGameOperateRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setGameNo(userData.getGameNo());
        if(type == 0){//结束游戏
            if(!ChineseChessMgr.activityInRewardPeriod() && eChineseChessGameStatusType.Revive.getValue() != userData.getGameStatus() && eChineseChessGameStatusType.Pass.getValue() != userData.getGameStatus()){
                return GameErrorCode.E_CHINESECHESS_GAME_ERR;
            }
            ChineseChessProto.CrossChineseChessGetRankChangeReqMsg.Builder msg = ChineseChessProto.CrossChineseChessGetRankChangeReqMsg.newBuilder();
            msg.setActivityId(activityId);
            msg.setConditionType(eGamePlayerEventType.ChineseChessTopScoreRank.getValue());
            msg.setGameNo(userData.getGameNo());
            msg.setLastScore(userData.getTopScore().longValue());
            msg.setNowScore(userData.getScore().longValue());
            msg.setIsPractice(false);
            player.sendPacket(CrossProtocol.C2_CHINESECHESS_ACTIVITY_GAME_OVER,msg);
            return 0;
        }
        else if(type == 1){//元宝重生
            if(ChineseChessMgr.isIngotRevive(userData.getIngotReviveTimes())){
                if(eChineseChessGameStatusType.Revive.getValue() != userData.getGameStatus()){
                    return GameErrorCode.E_CHINESECHESS_GAME_ERR;
                }
                long ingotCost = ChineseChessMgr.getIngotReviveCost(userData.getIngotReviveTimes());
                Property cost = PropertyHelper.parseStringToProperty(GameConfig.GAME_MONEY_INGOTS + "=" + ingotCost);
                if(!player.getModule(CurrencyModule.class).currencyIsEnough(cost)){
                    return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
                }
                player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.ChineseChessActivity,eLogMoneyType.ChineseChessActivityIngotRevive);
                userData.setGameStatus(eChineseChessGameStatusType.Running.getValue());
                userData.setIngotReviveTimes(userData.getIngotReviveTimes() + 1);
                ChineseChessData playerChess = userData.getChessMap().get(0);
                ChineseChessData removeChess = null;
                for(ChineseChessData chessData : userData.getChessMap().values()){
                    if(chessData.getChessNo() == 0)continue;
                    if(chessData.getPosition().getX() == playerChess.getPosition().getX() && chessData.getPosition().getY() == playerChess.getPosition().getY()){
                        removeChess = chessData;
                        continue;
                    }
                    respMsg.addChess(parseChineseChessDataPb(chessData));
                }
                long logAddScore = 0;
                List<ChineseChessData> logEatChessList = new ArrayList<>();
                String logChessDataStr = makeLogChessMapString(userData.getChessMap());
                if(removeChess != null){
                    logEatChessList.add(removeChess);
                    ChineseChessConfig removeChessConfig = ChineseChessMgr.getChessConfig(removeChess.getChessId());
                    logAddScore = getSkinAddScore(removeChessConfig);
                    userData.setScore(BigInteger.valueOf(userData.getScore().longValue() + getSkinAddScore(removeChessConfig)));
                    if(userData.getScore().compareTo(userData.getTopScore()) > 0){
                        noticeCondition(userData.getScore(),userData.getPassTime() > 0);
                    }
                    if(removeChess.getChessId() == eChineseChessPiecesType.King.getValue()){
                        userData.setPowerTimes(ChineseChessMgr.getEatKingPowerTime());
                    }
                    userData.getChessMap().remove(removeChess.getChessNo());
                    respMsg.setScore(userData.getScore().longValue());
                }
                addLog(eChineseChessLogTypeType.YuanBaoRevive.getValue(),0,logAddScore,logEatChessList,logChessDataStr,"");
            }else{
                return GameErrorCode.E_CHINESECHESS_GAME_ERR;
            }
        }
        else if(type == 3){//切换皮肤
            ChineseChessConfig chessConfig = ChineseChessMgr.getChessConfigBySkinId(skinId);
            if(chessConfig == null){
                return GameErrorCode.E_CHINESECHESS_GAME_ERR;
            }
            Map<Integer, ChineseChessSkinData> skinDataMap = userData.getChessSkinMap();
            ChineseChessSkinData chessSkinData = skinDataMap.get(chessConfig.getId());
            List<Integer> skinIdList = chessSkinData.getSkinIdList();
            if(!skinIdList.contains(skinId)){
                //skinId就是皮肤
                GoodsInfo goodsInfo = GoodsMgr.getGoodsById(skinId);
                if(goodsInfo == null){
                    return GameErrorCode.E_CHINESECHESS_GAME_ERR;
                }
                Property cost = PropertyHelper.parseStringToProperty(skinId + "=" + 1);
                if(!player.getModule(CurrencyModule.class).currencyIsEnough(cost)){
                    return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
                }
                player.getModule(CurrencyModule.class).removeCurrency(cost,eLogMoneyType.ChineseChessActivity,eLogMoneyType.ChineseChessActivityGameSkinActive);
                skinIdList.add(skinId);
                chessSkinData.setSkinIdList(skinIdList);
            }
            chessSkinData.setUseSkinId(skinId);
            userData.setChessSkinMap(skinDataMap);
        }
        player.sendPacket(Protocol.U_CHINESECHESS_GAME_OPERATE, respMsg);
        crossSyncUserData();
        return 0;
    }

    //是不是生成帅
    private boolean isKingNext(Map<Integer, ChineseChessData> nextChessMap){
        for(ChineseChessData chess : nextChessMap.values()){
            if(chess.getChessId() == eChineseChessPiecesType.King.getValue()){
                return true;
            }
        }
        return false;
    }

    //新版生成棋子
    private void makeNextNewVersion(){
        Map<Integer,ChineseChessData> nextChessMap = ChineseChessMgr.getNextChessMap(userData.getStep(),userData.getChessCount());
        if(nextChessMap == null){
//            log.error("生成下一轮棋子炸了");
            userData.setNextChessTurn(0);
            userData.setNextChessMap(new ConcurrentHashMap<>());
        }else{
            userData.setNextChessTurn(ChineseChessMgr.getNextChessTurn(userData.getStep()));
            userData.setChessCount(userData.getChessCount() + nextChessMap.size());
            userData.setNextChessMap(nextChessMap);
        }
    }

    //进入游戏，如果游戏在一半就继续玩，如果是结束状态就直接扣体力下一局，没体力就玩不了
    public int gameInto(int activityId){
//        userData = null;
//        initUserData(activityId);
        if(activityId != userData.getActivityId()){
            return GameErrorCode.E_ACTIVITY_NO_FOUND;
        }
        if(userData.getGameStatus() == eChineseChessGameStatusType.Over.getValue()){
            if(userData.getHp() <= 0){
                int recoverItemId = ChineseChessMgr.getPlayItemId();
                Property cost = PropertyHelper.parseStringToProperty(recoverItemId + "=" + 1);
                if(!player.getModule(CurrencyModule.class).currencyIsEnough(cost)){
                    return GameErrorCode.E_CHINESECHESS_GAME_NO_HP;
                }
                player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.ChineseChessActivity,eLogMoneyType.ChineseChessActivityGameStartItem);
            }
            if(userData.getHp() > 0){
                userData.setHp(userData.getHp() - 1);
            }
            newGameDataNewVersion(userData);
        }
        ChineseChessProto.ChineseChessIntoRespMsg.Builder msg = ChineseChessProto.ChineseChessIntoRespMsg.newBuilder();
        msg.setRet(0);
        msg.setGameNo(userData.getGameNo());
        List<ChineseChessData> chessList = new ArrayList<>(userData.getChessMap().values());
        for(ChineseChessData chess : chessList){
            if(chess.getChessNo() != 0){
                msg.addChess(parseChineseChessDataPb(chess));
            }
        }
        List<ChineseChessData> nextChessList = new ArrayList<>(userData.getNextChessMap().values());
        msg.setNextTurn(userData.getNextChessTurn());
        for(ChineseChessData chess : nextChessList){
            msg.addNextChess(parseChineseChessDataPb(chess));
        }
        msg.setSelfChess(parseChineseChessDataPb(userData.getChessMap().get(0)));
        msg.setGameStatus(userData.getGameStatus());
        msg.setReviveSelf(userData.getReviveSelfTimes());
        msg.setReviveTimes(userData.getIngotReviveTimes());
        msg.setScore(userData.getScore().longValue());
        msg.setIsReviveSelf(userData.isReviveSelf());
        msg.setPowerTimes(userData.getPowerTimes());
        msg.setStep(userData.getStep());
        msg.setPassTimes(userData.getPassTime());
        player.sendPacket(Protocol.U_CHINESECHESS_GAME_INFO, msg);
        return 0;
    }

    public int crossSyncUserData(){
        ChineseChessProto.CrossChineseChessGetRankReqMsg.Builder msg = ChineseChessProto.CrossChineseChessGetRankReqMsg.newBuilder();
        msg.setActivityId(userData.getActivityId());
        msg.setConditionType(eGamePlayerEventType.ChineseChessTopScoreRank.getValue());
        player.sendPacket(CrossProtocol.C2_CHINESECHESS_ACTIVITY_GAME_ENTER,msg);
        return 0;
    }

    public ChineseChessProto.ChineseChessData.Builder parseChineseChessDataPb(ChineseChessData chessData){
        ChineseChessProto.ChineseChessData.Builder tempMsg = ChineseChessProto.ChineseChessData.newBuilder();
        tempMsg.setChessNo(chessData.getChessNo());
        tempMsg.setChessId(chessData.getChessId());
        tempMsg.setX(chessData.getPosition().getX());
        tempMsg.setY(chessData.getPosition().getY());
        return tempMsg;
    }

    public ChineseChessProto.ChineseChessSkinDataMsg.Builder parseChineseChessSkinDataPb(ChineseChessSkinData skinData){
        ChineseChessProto.ChineseChessSkinDataMsg.Builder tempMsg = ChineseChessProto.ChineseChessSkinDataMsg.newBuilder();
        tempMsg.setChessId(skinData.getChessId());
        tempMsg.setSkinId(skinData.getUseSkinId());
        return tempMsg;
    }

    private List<Integer> getHasSkinIdList(){
        List<Integer> allSkinIdList = new ArrayList<>();
        Map<Integer, ChineseChessSkinData> chessSkinDataMap = userData.getChessSkinMap();
        for(ChineseChessSkinData skinData : chessSkinDataMap.values()){
            allSkinIdList.addAll(skinData.getSkinIdList());
        }
        return allSkinIdList;
    }

    @Override
    public boolean loadData() {
        if(SystemOpenMgr.systemOpen(player, eSystemId.ChineseChess.getValue())){
            ActivityInfo activityInfo = ChineseChessMgr.getActivityInfo();
            if(activityInfo != null){
                userData = ChineseChessBusiness.getUserData(getUserId(),activityInfo.getActivityId());
                if(userData == null){
                    initUserData(activityInfo.getActivityId());
                }
            }
        }
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return false;
    }

    @Override
    public boolean saveData() {
        /*if(ChineseChessMgr.isDebugUserId(player.getUserId())){
            debugAutoMove(0);
        }*/
        if(userData != null){
            if(userData.isInsertOption()){
                ChineseChessBusiness.addUserData(userData);
            }else if(userData.isUpdateOption()){
                ChineseChessBusiness.updateUserData(userData);
            }
        }
        return true;
    }

    @Override
    public void afterLogin() {
        if(SystemOpenMgr.systemOpen(player, eSystemId.ChineseChess.getValue())){
            ActivityInfo activityInfo = ChineseChessMgr.getActivityInfo();
            if(activityInfo != null){
                initUserData(activityInfo.getActivityId());
                syncConfigData();
                crossSyncUserData();
            }
        }
    }

    public void syncConfigData(){
        ChineseChessProto.ChineseChessConfigDataSyncMsg.Builder syncConfigDataMsg = ChineseChessProto.ChineseChessConfigDataSyncMsg.newBuilder();
        syncConfigDataMsg.setActivityId(ChineseChessMgr.getShowTimeActivityId());
        syncConfigDataMsg.setConfigData(ChineseChessMgr.getConfigDataTempBuilder(player.getLanguage()));
        player.sendPacket(Protocol.U_CHINESECHESS_CONFIG_SYNC, syncConfigDataMsg);
    }

    public void syncUserDataFromCorss(int rank){
        ChineseChessProto.ChineseChessUserDataSyncMsg.Builder syncUserDataMsg = ChineseChessProto.ChineseChessUserDataSyncMsg.newBuilder();
        syncUserDataMsg.setActivityId(ChineseChessMgr.getShowTimeActivityId());
        syncUserDataMsg.setHp(userData.getHp());
        //判断哪个是最高分
        if(userData.getScore().compareTo(userData.getTopScore()) > 0){
            syncUserDataMsg.setTopScore(userData.getScore().longValue());
        }else{
            syncUserDataMsg.setTopScore(userData.getTopScore().longValue());
        }
        syncUserDataMsg.setGameStatus(userData.getGameStatus());
        syncUserDataMsg.setTopRank(rank);
        for(ChineseChessSkinData chessSkinData : userData.getChessSkinMap().values()){
            syncUserDataMsg.addSkinData(parseChineseChessSkinDataPb(chessSkinData));
        }
        syncUserDataMsg.addAllSkinId(getHasSkinIdList());
        syncUserDataMsg.setIsBuySilverToken(userData.isBuySilverToken());
        syncUserDataMsg.setIsBuyGoldToken(userData.isBuyGoldToken());
        player.sendPacket(Protocol.U_CHINESECHESS_DATA_SYNC, syncUserDataMsg);
    }

    //每日充值hp
    private void resetHp(){
        if(DateHelper.getTodayZeroTimeStamp() != userData.getHpTime()){
            userData.setHp(ChineseChessMgr.getEveryHp());
            userData.setHpTime(DateHelper.getTodayZeroTimeStamp());
        }
    }

    public void initUserData(int activityId){
        if(userData == null || userData.getActivityId() != activityId){
            ChineseChessUserData tempUserData = new ChineseChessUserData();
            tempUserData.setActivityId(ChineseChessMgr.getShowTimeActivityId());
            tempUserData.setUserId(getUserId());
            tempUserData.setHp(ChineseChessMgr.getEveryHp());
            tempUserData.setHpTime(DateHelper.getTodayZeroTimeStamp());
            tempUserData.setTopScore(BigInteger.ZERO);
            tempUserData.setScore(BigInteger.ZERO);
            tempUserData.setStep(0);
            tempUserData.setChessCount(1);
            tempUserData.setGameNo(0);
            tempUserData.setShuaiTimes(0);
            tempUserData.setIngotReviveTimes(0);
            tempUserData.setPowerTimes(0);
            tempUserData.setGameStatus(eChineseChessGameStatusType.Over.getValue());
            tempUserData.setUpdateTime(System.currentTimeMillis());
            Map<Integer, ChineseChessData> chessMap = new ConcurrentHashMap<>();
            tempUserData.setChessMap(chessMap);
            Map<Integer, ChineseChessData> nextChessMap = new ConcurrentHashMap<>();
            tempUserData.setNextChessMap(nextChessMap);
            tempUserData.setChessSkinMap(ChineseChessMgr.getInitSkinData());
            tempUserData.setReviveSelf(false);
            tempUserData.setBuySilverToken(false);
            tempUserData.setBuyGoldToken(false);
            tempUserData.setInsertOption();
            userData = tempUserData;
        }
        resetHp();
    }

    public ChineseChessUserData newGameDataNewVersion(ChineseChessUserData userData){
        //只有2的状态才能重新开始游戏
        if(userData.getGameStatus() != eChineseChessGameStatusType.Over.getValue()){
            return null;
        }
        ChineseChessData self = new ChineseChessData();
        self.setChessNo(0);
        self.setChessId(eChineseChessPiecesType.Rooks.getValue());
        ChineseChessPosition chessPosition = ChineseChessMgr.getSelfPosition();
        self.setPosition(chessPosition);

        userData.setGameNo(userData.getGameNo() + 1);
        userData.setStep(0);
        userData.setScore(BigInteger.ZERO);
        userData.setShuaiTimes(0);
        userData.setReviveSelfTimes(0);
        userData.setPowerTimes(0);
        userData.setIngotReviveTimes(0);
        Map<Integer, ChineseChessData> chessMap = new ConcurrentHashMap<>();
        chessMap.put(self.getChessNo(),self);

        userData.setChessMap(chessMap);
        List<ChineseChessData> initialEnemyChessList = ChineseChessMgr.getInitialEnemyChessList();
        for(ChineseChessData chess : initialEnemyChessList){
            chessMap.put(chess.getChessNo(),chess);
        }
        userData.setChessCount(userData.getChessCount() + initialEnemyChessList.size());

        //生成下一次敌人
        userData.setNextChessTurn(ChineseChessMgr.getNextChessTurn(userData.getStep()));
        Map<Integer,ChineseChessData> nextChessMap = ChineseChessMgr.getNextChessMap(userData.getStep(),userData.getChessCount());
        if(nextChessMap == null){
            log.error("生成棋子配置异常");
        }else{
            userData.setChessCount(userData.getChessCount() + nextChessMap.size());
        }
        userData.setGameStatus(eChineseChessGameStatusType.Running.getValue());
        userData.setChessMap(chessMap);
        userData.setNextChessMap(nextChessMap);
        return userData;
    }

    /**
     * 系统解锁
     */
    public void initSystem() {
        ActivityInfo activityInfo = ChineseChessMgr.getActivityInfo();
        if(activityInfo != null){
            initUserData(activityInfo.getActivityId());
            syncConfigData();
            crossSyncUserData();
            ChineseChessPracticeModule modulePractice = player.getModule(ChineseChessPracticeModule.class);
            modulePractice.initPracticeUserData(activityInfo.getActivityId());
        }
    }



}
